home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Scheduling / Cassandra / Source / Event.m < prev    next >
Encoding:
Text File  |  1991-11-01  |  16.1 KB  |  680 lines

  1. //
  2. // Event.m
  3. // Copyright (c) 1988, 1989, 1990 by Jiro Nakamura 
  4. // All rights reserved
  5. //
  6. // Implementation definition of class Event. Event handles 
  7. // the database management of Cassandra.
  8. //
  9. // RCS Information
  10. // Revision Number->    $Revision: 2.11 $
  11. // Last Revised->    $Date: 91/11/01 17:24:00 $
  12. //
  13. static char rcsid[] = "$Id: Event.m,v 2.11 91/11/01 17:24:00 jiro Exp Locker: jiro $";
  14.  
  15. #import "Event.h"
  16. #import <objc/objc.h>
  17. #import <strings.h>
  18. #import <appkit/Panel.h>       /* for NXRunAlertPanel */
  19. #import "cass.h"    
  20. #import "calendar.h"
  21. #import "Global.h"
  22. #import "misc.h"
  23. #import <sys/types.h>
  24. #import <sys/stat.h>
  25.     
  26. // Defining DEBUG for Event can sometimes get very screen messy
  27. // since Cassandra uses it so often
  28. #ifdef DEBUG
  29.     #undef DEBUG
  30.     #define DEBUG2
  31. #endif
  32.  
  33. #define VERSION_15    1
  34. #define    EVENT_VERSION    1
  35.  
  36. int fgeti( int *i ,     FILE *fp)        
  37. {
  38.     char buffer[10];
  39.     if( fgets(buffer, 10, fp) == NULL || strlen( buffer ) < 1)
  40.         {
  41.         *i = 0;
  42.         return -1;
  43.         }
  44.     *i = atoi(buffer);
  45.     return 0;
  46. }
  47.         
  48.  
  49. @implementation Event
  50.  
  51. + newAt:(const char*) eFile
  52. {
  53.     self = [super new];
  54.     strcpy(eventFile,eFile);
  55.     
  56.     eventType = 0;
  57.     priority = 50;
  58.     destroy = snoozeNo = snoozeInt =0;
  59.     anniversary =  annvSpecial = 0;
  60.     present = next = previous = 0;
  61.     
  62.     strcpy(alarmSound, ALARMSOUND);
  63.     strcpy(msg,"empty");
  64.     return self;
  65. }
  66.  
  67. + new
  68. {
  69.     fprintf(stderr,"This should never be called!");
  70.     self = [super new];
  71.     return self;
  72. }
  73.  
  74. - free
  75. {
  76. #ifdef DEBUG
  77.     fprintf(stderr,"Event.m:Free ->Closing event!\n");
  78. #endif
  79.     [super free];
  80.     return nil;
  81. }
  82.  
  83. //
  84. //
  85. // Messages that affect how the file is stored on disk
  86. //
  87. //
  88.  
  89. - default: sender
  90. {
  91.     present =  0;
  92.     previous = next = -1;
  93.     destroy =  1;
  94.     anniversary = annvSpecial = snoozeInt = snoozeNo = priority = 0;
  95.     ts.tm_sec =  ts.tm_min =  ts.tm_hour = 0;
  96.     ts.tm_mday = ts.tm_mon =  ts.tm_year = 0;
  97.     ts.tm_wday =  ts.tm_yday =  ts.tm_isdst = 0;
  98.     alarmAction = playSound;
  99.     
  100.     strcpy(msg, "");
  101.     strcpy(alarmSound,[global alarmSound]);
  102.     return self;
  103. }
  104.  
  105.  
  106. - readEvent: (EFileLink) here        /* read itself from the event file */
  107. {
  108.     FILE * source;
  109.     static char errormsg[128], buffer[255];
  110.     char *tp;    // temporary pointer
  111.     struct stat statBuf;
  112.     int tmp;
  113.     
  114.     #ifdef DEBUG
  115.         fprintf(stderr,    "------------------------\n"
  116.                     "[Event readEvent: %d]\n",here);
  117.     #endif
  118.  
  119.     if( here < 0)
  120.         {
  121.         NXRunAlertPanel("File Seek Error", 
  122.                 "Cannot seek to a negative number.",
  123.                  "OK",NULL,NULL);
  124.         strcpy(msg, "Illegal event/link value....");
  125.         return nil;
  126.         }
  127.         
  128.     /* Let's first check to make sure we aren't reading an empty file */
  129.     stat( eventFile, &statBuf);
  130.     if( statBuf.st_size < 100)    // It can not be this short
  131.         {
  132.         strcpy(msg, CASSANDRAVERSION);
  133.         next = previous = 0;
  134.         present = here;                    
  135.         [self writeEvent: here];
  136.         fprintf(stderr, "%s: Event list not initialized. "
  137.             "Initializing....\n",
  138.             PROGNAME);
  139.         return nil;
  140.         }
  141.  
  142.     sprintf(errormsg, "Error occured while trying to read event file %s", 
  143.         eventFile);
  144.     source = fileOpen(eventFile, "r+",errormsg);
  145.     
  146.     sprintf(errormsg,     "An fatal error occured when we were trying "
  147.                 "to seek to event number %d for reading event "
  148.                 "file %s.\n This program has crashed.", 
  149.                 here, eventFile);
  150.     if( fileSeek(source, here, errormsg) == NULL)
  151.         {
  152.         next = previous = -1;
  153.         present = here;
  154.         return nil;
  155.         }
  156.     
  157.     fgeti(&present, source);
  158.     if( present != here)
  159.         {
  160.         fprintf(stderr, 
  161.             "%s: File header gives %d instead of %d.\n"
  162.             "%s: We've most probably run out off the end of %s.\n"
  163.             PROGNAME ,present, here,
  164.             PROGNAME, [global eventFile]);
  165.         next = previous = -1;
  166.         present = here;
  167.         fclose(source);
  168.         return nil;
  169.         }
  170.     else
  171.         {
  172.         fgeti(&previous, source);
  173.         fgeti(&next, source);
  174.         }
  175.  
  176.     fgeti( &tmp, source);
  177.     version = tmp / 100;
  178.     eventType = tmp % 100;
  179.     fgets( buffer, 10, source);
  180.     
  181.     #ifdef DEBUG2
  182.         fprintf(stderr, "Version = %d\n", version);
  183.     #endif
  184.     
  185.     fgeti( &priority, source);
  186.     
  187.     switch( version)
  188.         {
  189.         case VERSION_15:
  190.             fgeti( &annvSpecial, source);
  191.             fgeti( &anniversary, source);
  192.             break;
  193.         case 0:
  194.         default:
  195.             fgeti( &destroy, source);
  196.             fgeti( &anniversary, source);
  197.             break;
  198.         }
  199.     #ifdef DEBUG2
  200.         fprintf(stderr, "Anniversary = %d\n", anniversary);
  201.         fprintf(stderr, "AnniversarySpecial = %d\n", annvSpecial);
  202.     #endif
  203.  
  204.     fgeti( &snoozeNo, source);
  205.     fgeti( &snoozeInt, source);
  206.     
  207.     fgets( buffer, 10, source);
  208.     fgets( buffer, 10, source);
  209.     
  210.     fgeti( &ts.tm_sec, source);
  211.     fgeti( &ts.tm_min, source);
  212.     fgeti( &ts.tm_hour, source);
  213.     fgeti( &ts.tm_mday, source);
  214.     fgeti( &ts.tm_mon, source);
  215.     fgeti( &ts.tm_year, source);
  216.     
  217.     switch( version)
  218.         {
  219.         case VERSION_15:
  220.             fgeti( &duration, source);
  221.             fgeti( &tmp, source);
  222.             alarmAction = tmp;
  223.             fgeti( &ts.tm_isdst, source);
  224.             break;
  225.         case 0:
  226.         default:
  227.             fgeti( &ts.tm_wday, source);
  228.             fgeti( &ts.tm_yday, source);
  229.             fgeti( &ts.tm_isdst, source);
  230.             break;
  231.         }
  232.     
  233.     fgets( alarmSound, 100, source);    // We gotta strip the final
  234.     tp = rindex( alarmSound, '\n');        // newline and replace it with
  235.     if( tp != NULL)                // a NULL character.
  236.         *tp = '\0';
  237.     
  238.     fgets( buffer, 10, source);
  239.     fgets( buffer, 10, source);
  240.     fgets( buffer, 10, source);
  241.     fgets( buffer, 10, source);
  242.  
  243.     fgets(msg,MESSAGE_SIZE,source);
  244.                 
  245.     ts.tm_wday = wday(ts.tm_mday, ts.tm_mon+1, 1900+ts.tm_year);
  246.     ts.tm_yday = yday(ts.tm_mday, ts.tm_mon+1, ts.tm_year+1900);
  247.  
  248.     fixTmStructure( &ts);
  249.     
  250.     switch( version)
  251.         {
  252.         case VERSION_15:
  253.             break;
  254.                     
  255.         default:
  256.         case 0:
  257.             switch( alarmSound[0] )
  258.                 {
  259.                 case '-':        // don't play alarm
  260.                     strcpy(buffer, alarmSound);
  261.                     strcpy(alarmSound, buffer+1);
  262.                     alarmAction = nothing;
  263.                     break;
  264.                 case '?':
  265.                     strcpy(buffer, alarmSound);
  266.                     strcpy(alarmSound, buffer+1);
  267.                     alarmAction = playAndDeleteSound;;
  268.                 break;
  269.                 case '!':
  270.                     strcpy(buffer, alarmSound);
  271.                     strcpy(alarmSound, buffer+1);
  272.                     alarmAction = runCommand;
  273.                     break;
  274.                 }
  275.             break;
  276.         }
  277.         
  278.         
  279.     if( msg[0] == ';')
  280.         {
  281.         char buf[MESSAGE_SIZE];
  282.         
  283.         strcpy(buf, msg);
  284.         strcpy(msg, buf+1);
  285.         showMessage = FALSE;
  286.         }
  287.     else
  288.         showMessage = TRUE;
  289.             
  290.     fclose(source);
  291.     return self;
  292. }
  293.                 
  294. - firstEvent
  295. {
  296.     #ifdef DEBUG
  297.         fprintf(stderr,"Reading in the first event.\n");
  298.     #endif
  299.  
  300.     [self readEvent : 0];
  301.     if( [self next] == 0)
  302.         return self;
  303.     [self readEvent : [self next]];
  304.     return self;
  305. }    
  306.     
  307. - writeEvent: (EFileLink) here    
  308. /* write itself into the event file using present as its index */
  309. {
  310.     FILE *source;
  311.     char errormsg[256], bufAlarm[256], bufMessage[256];
  312.         
  313.     if( here < 0)
  314.         {
  315.         NXRunAlertPanel( "Write Error", 
  316.                 "We can't write to a negative event number.",
  317.                 "OK",NULL,NULL);
  318.         return nil;
  319.         }
  320.         
  321.     #ifdef DEBUG
  322.         fprintf(stderr,    "------------------------\n"
  323.                 "[Event writeEvent: %d]: Opening event with "
  324.                 "<%s>!\n",here, eventFile);
  325.     #endif
  326.  
  327.     sprintf(errormsg, "Fatal error when trying to write to event file %s", 
  328.         eventFile);
  329.     source = fileOpen(eventFile, "r+",errormsg);
  330.     
  331.     sprintf(errormsg, "%s: An fatal error occured when we were trying to "
  332.             "seek to event number %d for writing in event file %s.\n"
  333.             " This program has crashed.", PROGNAME, here, eventFile);
  334.     fileSeek(source, here, errormsg);
  335.     
  336.     present = here;
  337.     
  338.     if( ts.tm_year > 1900)
  339.         ts.tm_year -= 1900;
  340.  
  341.     strcpy(bufAlarm, alarmSound);
  342.  
  343.     if( showMessage == FALSE)
  344.         {        
  345.         strcpy(bufMessage, ";");
  346.         strcat(bufMessage, msg);
  347.         }
  348.     else
  349.         strcpy(bufMessage, msg);
  350.  
  351.     #ifdef DEBUG2
  352.         fprintf(stderr, "wAnniversary = %d\n", anniversary);
  353.         fprintf(stderr, "wAnniversarySpecial = %d\n", annvSpecial);
  354.     #endif
  355.  
  356.  
  357.     if(fprintf( source,         
  358.                     "%d\n%d\n%d\n"
  359.                     "%d\n\n"
  360.                     "%d\n%d\n%d\n"
  361.                     "%d\n%d\n"
  362.                     "\n\n"
  363.                     "%d\n%d\n%d\n"
  364.                     "%d\n%d\n%d\n"
  365.                     "%d\n%d\n%d\n"
  366.                     "%s\n\n"
  367.                     "\n\n\n"
  368.                     "%s\n",
  369.                     present, previous, next,
  370.                     EVENT_VERSION * 100 + eventType,
  371.                     priority, annvSpecial, anniversary,
  372.                     snoozeNo, snoozeInt,
  373.                     ts.tm_sec, ts.tm_min, ts.tm_hour,
  374.                     ts.tm_mday, ts.tm_mon, ts.tm_year,
  375.                     duration, alarmAction, ts.tm_isdst,
  376.                     bufAlarm, bufMessage) == -1)
  377.         {
  378.         fprintf(stderr, "%s: Event.m:   Error occured writing file.",
  379.              PROGNAME);
  380.         strcpy(msg, "Error occured in writing out Elink number.\n\n");
  381.         fclose(source);
  382.         return nil;
  383.         }
  384.     
  385.         #ifdef DEBUG
  386.             fprintf(stderr, "%s: Wrote out Efilelink.\n  Here=%d,"
  387.                 "Previous = %d, Next=%d\n", PROGNAME,
  388.                 here, previous, next);
  389.             fprintf(stderr, "%s: Date:   time = %d:%d, day= %d, "
  390.                 "month = %d, year = %d.\n\n",PROGNAME,
  391.                 ts.tm_hour, ts.tm_min, ts.tm_mday, ts.tm_mon, 
  392.                 ts.tm_year);
  393.             fprintf(stderr,"%s: AlarmSound =%s\n", PROGNAME, bufAlarm);
  394.         #endif
  395.         
  396.     fclose(source);
  397.     return self;
  398. }
  399.  
  400. - (EFileLink) insertEvent
  401. {
  402.     return [self insertEventFrom : 1];
  403. }
  404.  
  405.  
  406.  
  407. /* insert itself into the file with current day as index */
  408. /* and starting from <here> in searching for a open deleted space */
  409. - (EFileLink) insertEventFrom : (EFileLink) here
  410. {
  411.     id event, step;
  412.     int loop;
  413.     
  414.  
  415.     // First things first, we must check the format of our time structure  
  416.     // since we have given other functions full freedom to scew it up
  417.  
  418.     fixTmStructure( &ts);
  419.             
  420.     event = [Event newAt:eventFile];
  421.     step = [Event newAt:eventFile];
  422.     [event readEvent:0];
  423.     for( [event readEvent: [event next]]; 
  424.           [event present] != 0 && timeCompare([event time], &ts) < 0;
  425.           [event readEvent:[event next]])
  426.               {
  427.               #ifdef DEBUG
  428.             fprintf(stderr, "From %d looping onto %d\n",
  429.                 [event present],[event next]);
  430.         #endif
  431.         }
  432.         
  433.         
  434.     if( timeCompare([event time], &ts)  == 0 )
  435.         {
  436.         if( NXRunAlertPanel("Scheduling Conflict?",  
  437.             "You have another "
  438.             "scheduled event at that time. Should I insert this "
  439.             "event anyway?", "Insert anyway", "Cancel it", 
  440.             NULL) == 0 )
  441.             [event free];
  442.             [step free];
  443.             return 0;
  444.         }
  445.             
  446.             
  447.             
  448.     #ifdef DEBUG    
  449.         fprintf(stderr, "inserting between %d <- event -> %d.\n",
  450.             [event previous], [event present]);
  451.     #endif
  452.     
  453.     previous = [event previous];
  454.     next = [event present];
  455.     
  456.     [step setNext: 0];
  457.     for( loop = here; !([step next] == -1 && [step previous] == -1); [step readEvent: loop++])
  458.         {
  459.         #ifdef DEBUG
  460.             fprintf(stderr, "reading at %d.\n",loop);
  461.         #endif
  462.         }
  463.         
  464.     present = [step present];
  465.     
  466.     [self writeEvent: present];
  467.     
  468.     [step readEvent: previous];
  469.     [step setNext : present];
  470.     [step writeEvent:previous];
  471.     
  472.     [step readEvent: next];
  473.     [step setPrevious : present];
  474.     [step writeEvent:next];
  475.     
  476.     [step free];
  477.     [event free];
  478.     #ifdef DEBUG
  479.         fprintf(stderr,"successfully inserted %d <- %d -> %d\n\n",[self previous],[self present], [self next]);
  480.     #endif
  481.  
  482.     
  483.     return( [self present] );
  484. }
  485.  
  486. /* delete itself from the file with present as index */
  487. - deleteEvent  : (EFileLink) here 
  488. {
  489.     id previousEvent, nextEvent;
  490.     
  491.     #ifdef DEBUG
  492.         fprintf(stderr, "Deleting <%d>\n\n",here);
  493.     #endif
  494.     
  495.     if( here <= 0)
  496.         {
  497.         NXRunAlertPanel(NULL,"You cannot delete link 0 or below. OK?",
  498.                  "Shucks...",NULL,NULL);
  499.         fprintf(stderr,"Can't delete the header.  Here = %d.\n\n",
  500.              here);
  501.         return nil;
  502.         }
  503.     
  504.     previousEvent= [Event newAt: eventFile];
  505.     nextEvent = [Event newAt:eventFile];
  506.     
  507.     [previousEvent readEvent  :here];
  508.     if( ( [previousEvent previous] == -1  )   || 
  509.         ( [previousEvent next]  == -1  )        )
  510.         {
  511.         /*   link was already deleted, so we can't delete it..... */
  512.         strcpy(msg, "Can't delete link because it's already been "
  513.             "deleted!?!\n\n");
  514.         return nil;
  515.         }
  516.     
  517.     /* Set the previous_link of the next link */
  518.     /* to the one of the previous one */                    
  519.     [nextEvent readEvent :[previousEvent next]];    
  520.     [nextEvent setPrevious  : [previousEvent previous]];            
  521.     [nextEvent writeEvent  :[previousEvent next]];    
  522.     
  523.     /* do the same confusing spiel for previous */
  524.     [nextEvent readEvent  :[previousEvent previous] ];    
  525.     [nextEvent setNext  : [previousEvent next]];
  526.     [nextEvent writeEvent  :[previousEvent previous] ];
  527.     
  528.     /* cancel out the header to finally kill it */
  529.     /* and write it out */
  530.     [previousEvent setNext  : -1];    
  531.     [previousEvent setPrevious  :-1];    
  532.     [previousEvent writeEvent  :here];    
  533.     
  534.     #ifdef DEBUG
  535.         fprintf(stderr, "Record %d successfully deleted.\n\n", 
  536.             here);
  537.     #endif
  538.     
  539.     [previousEvent free];
  540.     [nextEvent free];
  541.     return self;
  542. }
  543.  
  544. /* delete if it is not an anniversary event, update otherwise */
  545. - (int) murderEvent : (EFileLink) here
  546. {
  547.     Event *event;
  548.     
  549.     #ifdef DEBUG
  550.         fprintf(stderr,"Arrggh! Help! I'm getting murdered! "
  551.             "(says Event <%d>)\n\n",
  552.             here);
  553.     #endif
  554.     
  555.     event = [Event newAt :eventFile];
  556.     [event readEvent : here];        //    Read the event in
  557.     [event deleteEvent : here];        //    Delete the event
  558.     
  559.     if( (int) ([event anniversary]/100) == 0)        // No anniversary
  560.         return -1;
  561.         
  562.     [event setTime: fixAnniversary( [event time], [event anniversary], 
  563.         [event annvSpecial])];
  564.     //     Fix the next event time and reinsert it
  565.                                 
  566.     // Use the same EFilelink space that we deleted, this saves 
  567.     // us time and maybe some confusion 
  568.     return( [event insertEventFrom:here]  );
  569. }
  570.  
  571.  
  572. - setMday : (int) x    { ts.tm_mday = x;    return self; }
  573. - setMon: (int) x    { ts.tm_mon = x; return self; }
  574. - setYear: (int) x    { ts.tm_year = x; return self; }
  575.     
  576. - setHour: (int) x    { ts.tm_hour = x;    return self; }
  577. - setMin: (int) x    { ts.tm_min = x; return self; }
  578. - setSec: (int) x    { ts.tm_sec = x; return self; }
  579. - setDestroy : (int) dst    { destroy = dst; return self; }
  580. - setAnniversary : (int) anv    { anniversary = anv; return self; }
  581. - setAnnvSpecial : (int) anvS    { annvSpecial = anvS; return self; }
  582. - setSnoozeNo : (int) sn    { snoozeNo = sn; return self; }
  583. - setSnoozeInt : (int) si    { snoozeInt = si; return self; }
  584. - setPriority : (int) si     { priority = si; return self; }
  585. - setAlarmSound : (char *) aS    { strcpy(alarmSound,aS); return self; }
  586. - setShowMessage: (BOOL) aFlag    { showMessage = aFlag; return self; }
  587. - setMessage : (char *) message { strcpy( msg, message); return self; }
  588. - setWday : (int) wd        { ts.tm_wday = wd; return self; }
  589. - setYday : (int) yd        { ts.tm_yday = yd;  return self; }
  590. - setPresent : (EFileLink) apresent    { present = apresent; return self; }
  591. - setPrevious  : (EFileLink) aprevious    { previous =aprevious; return self; }
  592. - setNext  : (EFileLink) anext        { next = anext; return self; }
  593. - setTime : (struct tm *) time        { ts = *time; return self; }
  594.  
  595.  
  596. - setPlayAlarm: (BOOL) aFlag    { alarmAction = playSound; return self; }
  597. - setMailPerson:(BOOL) aFlag    { alarmAction = mailPerson; return self; }
  598. - setRunCommand: (BOOL) aFlag    { alarmAction = runCommand; return self; }
  599. - setDeleteSound: (BOOL) aFlag    { alarmAction = playAndDeleteSound; 
  600.                     return self; }
  601.  
  602. - setAlarmAction: (int) aa    { alarmAction = aa; return self; }
  603.  
  604. - (EFileLink) present    { return present; }
  605. - (EFileLink) previous    { return previous; }
  606. - (EFileLink) next    { return next; }
  607.  
  608. - (char *) message    { return msg; }
  609. - (char *) alarmSound    { return alarmSound; }
  610.  
  611. - (BOOL) deleteSound    { return alarmAction == playAndDeleteSound;    }
  612. - (BOOL) playAlarm    { return (alarmAction == playAndDeleteSound ||
  613.                 alarmAction == playSound) ; }
  614. - (BOOL) runCommand    { return  alarmAction == runCommand; }
  615. - (BOOL) mailPerson    { return alarmAction == mailPerson; }
  616. - (BOOL) showMessage    { return showMessage; }
  617.  
  618. - (int) alarmAction    { return alarmAction; }
  619.  
  620. - (int) anniversary    { return anniversary; }
  621. - (int) annvSpecial    { return annvSpecial; }
  622. - (int) destroy        { return destroy; }
  623. - (int) hour        { return (ts.tm_hour); }
  624. - (int) mday;        { return( ts.tm_mday); }
  625. - (int) min        { return(ts.tm_min); }
  626. - (int) mon        { return (ts.tm_mon); }
  627. - (int) priority    { return priority; }
  628. - (int) sec        { return(ts.tm_sec); }
  629. - (int) snoozeInt    { return snoozeInt; }
  630. - (int) snoozeNo    { return snoozeNo; }
  631. - (int) wday        { return ts.tm_wday; }
  632. - (int) yday        { return ts.tm_yday; }
  633. - (int) year        { return (ts.tm_year); }
  634.  
  635. - (struct tm *) time    { return &ts; }
  636.  
  637. @end        
  638.  
  639.  
  640. struct tm *fixAnniversary( struct tm *time, int mode, int sub)
  641. {
  642.     #ifdef DEBUG
  643.     fprintf(stderr,"Fixing weekly special: %s, %d, %d\n", ascMyTime(time, YES, NO), 
  644.         mode, sub);
  645.     #endif
  646.  
  647.     switch( (int) mode  / 100)      
  648.         {
  649.         /* Don't worry about overflows as we add intervals to */
  650.         /* our dates, insertEvent is smart enough to handle it */
  651.         case 0:
  652.             return time;    /* No anniversary */
  653.         case 1:            /* If it is a day anniversary */
  654.             time->tm_mday+=  (mode - 100);
  655.             break;
  656.         case 2:            /* Weekly anniversary */
  657.             time -> tm_mday +=  ((mode - 200) * 7 );
  658.             break;
  659.         case 3:            /* Monthly anniversary */
  660.             time-> tm_mon += (mode - 300);
  661.             break;
  662.         case 4:            /* Yearly anniversary */
  663.             time -> tm_year +=  (mode - 400);
  664.             break;
  665.         case 5:            /* Special weekly */
  666.         default:
  667.              fprintf(stderr,
  668.                 "%s: I do not recognize "
  669.                 "anniversary event: %d.\n", 
  670.                 PROGNAME,
  671.                  mode);
  672.              return time;
  673.         }
  674.  
  675.     fixTmStructure( time);
  676.     return time;
  677. }
  678.  
  679.  
  680.